package com.neu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.neu.base.AuthContants;
import com.neu.base.Result;
import com.neu.entity.*;
import com.neu.entity.DTO.RegisterForm;
import com.neu.entity.security.LoginUser;
import com.neu.service.*;
import com.neu.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;


import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class AuthenticationServiceImpl implements AuthenticationService {

    @Autowired
    UserService userService;
    @Autowired
    ProjectUserRoleService projectUserRoleService;
    @Autowired
    RoleService roleService;
    @Autowired
    TaskUserService taskUserService;
    @Autowired
    NoticeUserService noticeUserServce;
    @Autowired
    TenantService tenantService;


    @Autowired
    RedisUtil redisUtil;

    /**
     * 根据用户名，封装用户信息，包括权限和角色
     *
     * @param username 用户名
     * @return
     */
    @Override
    public LoginUser login(String username) {
        LoginUser loginUser = new LoginUser();
        //先从用户表中查出来
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        User user = userService.getOne(queryWrapper);
        BeanUtil.copyProperties(user, loginUser);
        String userId = user.getUserId();
        //查询用户角色
        List<ProjectUserRole> projectUserRole = projectUserRoleService.getRoleIdsByUserId(userId);
        //将角色放入权限中
        //Arrays.asList() 返回的列表是不可变的，这就导致使用 add() 方法时会抛出 UnsupportedOperationException 异常。
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(loginUser.getDefaultRole())); // 默认角色
        if (projectUserRole != null) {

            Set<Role> roles = roleService.getRoleIdsById(projectUserRole.stream().map(ProjectUserRole::getRoleId).collect(Collectors.toSet()));
            System.out.println(roles);
            roles.forEach(role -> {
                authorities.add(new SimpleGrantedAuthority(role.getRoleCode()));
            });
            //将项目id放入
            //Collectors.toMap() 时，遇到重复的键（key）时会抛出 IllegalStateException 异常
            Map<String, List<String>> proRoleMap = projectUserRole.stream()
                    .collect(Collectors.groupingBy(
                            ProjectUserRole::getProjectId, // 按项目ID分组
                            Collectors.mapping(ProjectUserRole::getRoleId, Collectors.toList()) // 将角色ID存入列表
                    ));

            loginUser.setProjectIdMap(proRoleMap);
        }

        loginUser.setAuthorities(authorities);
        loginUser.setAuthorityStrings(authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));

        //查询用户的任务id
        List<TaskUser> tasks = taskUserService.getTaskIdsByUserId(userId);
        if (tasks != null) {
            List<String> taskIds = tasks.stream().map(TaskUser::getTaskId).collect(Collectors.toList());
            loginUser.setTaskIdList(taskIds);
        }

        //查询用户的通知id
        List<NoticeUser> noticeUsers = noticeUserServce.getNoticeIdsByUserId(userId);
        if (noticeUsers != null) {
            List<String> noticeIds = noticeUsers.stream().map(NoticeUser::getNoticeId).collect(Collectors.toList());
            loginUser.setNoticeIdList(noticeIds);
        }
        //查询租户信息
        Tenant tenant = tenantService.getById(user.getTenantId());
        loginUser.setTenantName(tenant.getTenantName());
        return loginUser;
    }

    @Override
    public Result register(RegisterForm registerForm) {

        String registerType = registerForm.getRegisterType();
        String username = registerForm.getUsername();
        String password = registerForm.getPassword();
        String email = registerForm.getEmail();
        String phone = registerForm.getPhone();
        String tenantName = registerForm.getTenantName();
        String captcha = registerForm.getCaptcha();

        String  right = (String)redisUtil.get(AuthContants.REDIS_KEY_AUTH_CAPTCHA + username);
        if(!captcha.equals(right)){

            return Result.error("验证码错误");
        }

        //管理员新增
        if (checkUsername(username)) {
            return Result.error("用户名已存在");
        }
        if(registerType.equals("phone")){
            if (checkPhone(phone)) {
                return Result.error("手机号已存在");
            }
            //验证一下手机号长度
            if(phone.length()!=11){
                return Result.error("手机号格式错误");
            }
        }else{
            if (checkEmail(email)) {
                return Result.error("邮箱已存在");
            }
            //验证一下邮箱格式
            if(!email.contains("@")){
                return Result.error("邮箱格式错误");
            }
        }
        if (!checkTenantName(tenantName)) {
            return Result.error("租户不存在");
        }
        //新增用户
        User user = new User();
        user.setUsername(username);
        user.setNickname(username);
        user.setAvatar("http://152.136.42.110:9115/swpt/1731596223526_8.png");
        user.setGender("1");
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encode = encoder.encode(password);
        user.setPassword(encode);
        user.setEmail(email);
        user.setPhone(phone);
        user.setTenantId(tenantService.getOne(new LambdaQueryWrapper<Tenant>().eq(Tenant::getTenantName, tenantName)).getTenantId());
        user.setDefaultRole("ROLE_user");
        user.setStatus("1");
        user.setRegisterType("1");
        user.setDelFlag("1");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userService.save(user);

        return Result.success("注册成功");
    }

    private boolean checkUsername(String username) {
        //如果存在返回true
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, username);
        return userService.getOne(queryWrapper) != null;
    }

    private boolean checkEmail(String email) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail, email);
        return userService.getOne(queryWrapper) != null;
    }

    private boolean checkPhone(String phone) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        return userService.getOne(queryWrapper) != null;
    }

    private boolean checkTenantName(String tenantName) {
        LambdaQueryWrapper<Tenant> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Tenant::getTenantName, tenantName);
        return tenantService.getOne(queryWrapper) != null;
    }
}
